package crap;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import java.awt.geom.AffineTransform;
import java.awt.geom.Line2D;
import java.awt.geom.NoninvertibleTransformException;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;

import javax.swing.JComponent;
import javax.swing.JFrame;

import Jama.Matrix;

import tools.Arrow;
import uebung03.Aufgabe05;

public class AffineTester01 {
	public static void main(String[] args) {
		final double scale = 2;
		JFrame ff = new JFrame();
		ff.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		final ArrayList<Pair<Point2D, Point2D>> pairs = new ArrayList<Pair<Point2D,Point2D>>();

		pairs.add(new Pair<Point2D, Point2D>(new Point2D.Double(100,180), new Point2D.Double(155, 250)));
		pairs.add(new Pair<Point2D, Point2D>(new Point2D.Double(360,100), new Point2D.Double(56, 180)));
		pairs.add(new Pair<Point2D, Point2D>(new Point2D.Double(220,370), new Point2D.Double(400, 200)));
		pairs.add(new Pair<Point2D, Point2D>(new Point2D.Double(109,307), new Point2D.Double(154, 300)));
		pairs.add(new Pair<Point2D, Point2D>(new Point2D.Double(410,320), new Point2D.Double(250, 300)));

		Matrix kov = new Matrix(pairs.size(), 4);
		Matrix p_= new Matrix(pairs.size(),1);

		final Rectangle2D rect = new Rectangle2D.Double(100, 100, 200, 200);
		
		for (int i = 0; i<pairs.size(); i++) {
			Pair<Point2D, Point2D> pair = pairs.get(i);
			double px = pair.a.getX(), py = pair.a.getY(), px_ = pair.b.getX(), py_ = pair.b.getY();
			kov.set(i, 0, px-py);
			kov.set(i, 1, -px-py);
			kov.set(i, 2, 1);
			kov.set(i, 3, -1);
			p_.set(i, 0, px_-py_);
		}
		
		Matrix kovT = kov.transpose();
		
		Matrix S = kovT.times(kov);
		Matrix STp_ = kovT.times(p_);
		
		final AffineTransform at = new AffineTransform();
		try {
			Matrix result = S.solve(STp_); 
			at.setTransform(result.get(0, 0), result.get(1, 0), -result.get(1, 0), result.get(0, 0), result.get(2, 0), -result.get(3, 0));
			System.out.println(at);
		}
		catch (Exception e) {
			e.printStackTrace();
		}
		
		
		final AffineTransform zoom = new AffineTransform();
		
		final JComponent canvas = new JComponent() {
			{setPreferredSize(new Dimension(800,700));}
			Arrow arrw = new Arrow();
			@Override
			public void paint(Graphics g) {
				Graphics2D g2 = (Graphics2D)g;
				
		        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
		        g2.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
		        g2.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
		        g2.transform(zoom);
				
//		        for (int i = 0; i<pairs.size(); i++) {
//		        	
//		        }
				for (Pair<Point2D, Point2D> p : pairs) {
					arrw.setArrow(p.a, p.b, scale*1, scale*2*Aufgabe05.gz);
					g2.setColor(Color.magenta);
					g2.fill(arrw);
					g2.setColor(Color.black);
					g2.draw(arrw);
					
				}
//		        g2.transform(at);
		        g2.draw(at.createTransformedShape(rect));
				super.paint(g);
			}
		};
		canvas.addMouseWheelListener(new MouseWheelListener() {

			@Override
			public void mouseWheelMoved(MouseWheelEvent e) {

				double scale = Math.pow(1.01, e.getWheelRotation());

				try {
					Point2D p = new Point2D.Double(e.getX(), e.getY());
					zoom.inverseTransform(p, p);
					zoom.concatenate(AffineTransform.getTranslateInstance(p.getX(), p.getY()));
					zoom.concatenate(AffineTransform.getScaleInstance(scale,scale));
					zoom.concatenate(AffineTransform.getTranslateInstance(-p.getX(), -p.getY()));

				} catch (NoninvertibleTransformException nte) {
					nte.printStackTrace();
				}
				canvas.repaint();
			}
		});
		
		
		
		
		ff.add(canvas);
		
		ff.pack();
		ff.setVisible(true);
	}
}
